package engine.net
{
	import engine.data.ModelLocator;
	import engine.logic.ActSee;
	import engine.logic.login.LoginAlert;
	import engine.logic.login.LoginUI;
	import engine.logic.login.WaitingForScene;
	import engine.net.datatype.ByteArrayEx;
	import engine.net.event.MsgEvent;
	import engine.ui.AlertUI;
	
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.Socket;
	import flash.net.URLRequest;
	import flash.net.navigateToURL;
	import flash.system.System;
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	import flash.utils.getTimer;
	
	import newx.BaseObject;
	import newx.com.config.StaticIni;
	import newx.utils.debug.IO;

	/**
	 * 处理数据流进出 
	 * @author wangjun
	 * 
	 */    
	public class NetSocket extends BaseObject
	{
		public		static var serialNum		:int 		= 0;
		public		static var count			:int 		= 0;
		public		static var returnCount		:int 		= 0;
		private 	static var _self			:NetSocket 	= null;
		private 			var socket			:Socket;
		private 			var endFlag			:int 		= 0xEE;
		private 			var msgBuffer		:ByteArrayEx;
		private 			var strHost			:String;
		private 			var iPort			:int;
		
		private 			var sendBuff		:Array;
		
//		private 			var eventTimer	:Timer;
		
		private			var _time			:int;
		
		/**是否正在解析消息*/
		private 			var _isRun			:Boolean	=	false;
		
		private 			var _sprite			:Sprite		=	new Sprite();
		
		/**消息数/每帧*/
		public				var _countForFrame	:int 		= 0;
		
		/**获取网络接口*/
		static public function getInstance():NetSocket
		{
			if (NetSocket._self != null)
			{
				return NetSocket._self;
			}
			else
			{
				NetSocket._self = new NetSocket();
				return NetSocket._self;
			}
		}
		
		public function get connected():Boolean
		{
			
			return socket.connected;
		}
		
		public function NetSocket(target:IEventDispatcher=null)
		{
			super(target);
			
			socket 			= 	new Socket();
			socket.endian 	= 	Endian.LITTLE_ENDIAN;
			
			msgBuffer 		= 	new ByteArrayEx();
			sendBuff		=	new Array();
			
			socket.addEventListener(Event.CLOSE, oncloseHandler);
			socket.addEventListener(Event.CONNECT, onconnectHandler);
			socket.addEventListener(IOErrorEvent.IO_ERROR, onioErrorHandler);
			socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onsecurityErrorHandler);
//			socket.addEventListener(ProgressEvent.SOCKET_DATA, onRecive);
			
//			eventTimer	=	new Timer(50);
//			
//			eventTimer.addEventListener(TimerEvent.TIMER,onCheck);
//			
//			eventTimer.start();
		}
		
		
		//进行socket连接
		public function Connect(HostName : String,HostPort : Number, bconnect:Boolean = true):void
		{
			//配置socket的接收和发送
			if (bconnect)
			{
				_time = getTimer();
				socket.connect(HostName, HostPort);
			}
			this.strHost = HostName;
			this.iPort = HostPort;	
		}
		/**
		 * 进行socket连接，在以知地址和端口的情况下 
		 * 
		 */		
		public function ConnectEx():void
		{
			//配置socket的接收和发送
			socket.connect(this.strHost, this.iPort);
		}
		
		//执行socket关闭
		public function Close():void
		{
			if(socket)	socket.close();
		}
		
		/**
		 * 发送消息（自动缓冲消息） 
		 * @param p_byteArray
		 * 
		 */		
		public function send(p_byteArray:ByteArrayEx):void
		{	
//			IO.traceLog("发送命令->");
			if (socket == null || socket.connected == false)
			{
				sendBuff.push(p_byteArray);
				return;
			}
			
			var bt:ByteArray = p_byteArray;
			//var isEndFlag:Boolean = false;
			
			//try {
				if (p_byteArray != null){
					// 如果消息中存在和结束标记一样的字符则在最后加0x00
					bt = solveEndFlagClash(bt, 0xee, 0x00);
					
					// 给每条消息增加结束标记
					bt.writeByte(endFlag);
					bt.writeByte(endFlag);
					
					socket.writeBytes(bt);
					socket.flush();
//					IO.traceLog("have send msg");
					
				}
			/*} catch (p_e:Error){
				//dispatchEvent(new Event(CONNECT_FALSE));
				IO.traceLog(p_e.getStackIO.traceLog());
			}*/
		}
		/**
		 * 处理发送的字符串存在0xEE的问题
		 */
		private function solveEndFlagClash(p_ByteArray:ByteArray, p_flag:int, p_insert:int):ByteArray
		{
			p_ByteArray.position = 0;
			//检查到0xEE	就在后面加0x00,
			while(p_ByteArray.bytesAvailable != 0){
				if (p_ByteArray.readUnsignedByte() == p_flag){
					var bt:ByteArray = new ByteArray();
					bt.endian = Endian.LITTLE_ENDIAN;
					bt.writeBytes(p_ByteArray, 0, p_ByteArray.position);
					bt.writeByte(p_insert);
					bt.writeBytes(p_ByteArray, p_ByteArray.position, p_ByteArray.bytesAvailable);
					bt.position = p_ByteArray.position;
					p_ByteArray = bt;
				}
			}
			
			p_ByteArray.position = p_ByteArray.length;
			
			return p_ByteArray;
		}
		//执行数据接收
//		private function onRecive(event : Event):void
//		{
//            if (socket.bytesAvailable > 4)
//            {
//				receiveData();
//			}
//		}
		
//		private function onCheck(event:TimerEvent):void
//		{
//			var t:int	=	getTimer();
//			try
//			{
//				if (socket.bytesAvailable > 4)
//				{
//					if(!_isRun)
//					{
////						trace("start");
//						_isRun	=	true;
//						receiveData(t);
//					}
//					else
//					{
////						trace("waitting...");
//					}
//				}
//			}
//			catch(e:Error)
//			{
//			}
//		}
		
		/**
		 * 帧检测
		 * @param e
		 * 
		 */		
		private function onCheck(e:Event):void
		{
			_countForFrame	=	getTimer();
			receiveData(_countForFrame);
		}
		
		
//		private function receiveData(val:int):void
//		{
		private function receiveData(val:int):void
		{
			
			if(getTimer() - val > 60)
			{
				returnCount++;
				return;
			}
			
			var tempBt:ByteArray = new ByteArray();
			var num:Number = socket.bytesAvailable;
			while(socket.bytesAvailable > 0)
			{
				var byte:int = socket.readUnsignedByte();
				if (byte == endFlag)
				{
					if (tempBt.length == 1)
					{
						
						// 接收到两个连续的结束标志，消息结束，
						msgBuffer.position = 0;
						// 输出当前缓存中的消息
						outputByteArray();
						// 接收完消息后如果还有未接收的部分则继续放入消息缓存队列中
						if (socket.bytesAvailable > 0)
						{
							receiveData(val);
						}
						break;
					}
					else
					{
						tempBt.writeByte(byte);
					}
				}
				else
				{
					if (tempBt.length == 1 && byte == 0x00)
					{
						// 如果字符串中包含0XEE0X00，则后面的0X00为无效字符，不做处理
					}
					else
					{
						tempBt.writeByte(byte);
					}
					msgBuffer.writeBytes(tempBt, 0, tempBt.length);
					tempBt = new ByteArray();
				}
			}
//			trace("over",socket.bytesAvailable,msgBuffer.position)
			_isRun	=	false;
		}

		/**
		 * 派发收到的消息
		 */
		private function outputByteArray():void
		{
			count++;
//			if(testNet.count == 999)
//			{
//				IO.traceLog("->",testNet.count,getTimer());
//				return;
//			}
			var preMemory:Number	=		System.totalMemory * 0.000000954
			var lastMemory:Number	
//			IO.traceLog("收到消息"," 当前内存：", preMemory);
			dispatchEvent(new MsgEvent(msgBuffer));
//			IO.traceLog("处理完消息"," 当前内存：",lastMemory=System.totalMemory * 0.000000954," 内存增加：",lastMemory-preMemory);
			msgBuffer = new ByteArrayEx();
			msgBuffer.endian = Endian.LITTLE_ENDIAN;
		}
		
		//以下五个私有方法为监听后的事件处理
		private function oncloseHandler(event:Event):void
		{
			_sprite.removeEventListener(Event.ENTER_FRAME,onCheck);
			
			ActSee.PostLoginStatus(8814,1,getTimer() - _time);
			
		    this.dispatchEvent(event);
		    //SN_PopInfo.GetInstance().ShowSimpleInfo(0, 0, "closeHandler: " + String(event), false, SN_PopInfo.PopInfo_Pos_Center);
			IO.traceLog("closeHandler: " + event);
//			this.Close();
//			LoginAlert.hide();
			
			if(	ModelLocator.Gameing	==	ModelLocator.getInstance().gameStatus)
			{
				AlertUI.showAlert(StaticIni.getSwfLangStr("刷新页面"),StaticIni.getSwfLangStr("断开连接，点击确定按钮可以重新登录"),AlertUI.OK,
					function(type:int, str:String, clickData:*):void{
					if(type == AlertUI.OK)
					{
						var url:String	=	ModelLocator.getInstance().mainIni.getContent("loginConfig","homesite");
						navigateToURL( new URLRequest(url),"_self");
//						navigateToURL( new URLRequest("javascript:window.location.reload(false);"), "_self" );
					}
				})			
			}
			
			ModelLocator.getInstance().gameStatus	=	ModelLocator.None;
		}
		
		private function onconnectHandler(event:Event):void
		{
			_sprite.removeEventListener(Event.ENTER_FRAME,onCheck);
			_sprite.addEventListener(Event.ENTER_FRAME,onCheck);
			
			ActSee.PostLoginStatus(22001,1,getTimer() - _time);

//			socket.removeEventListener(Event.CONNECT, onconnectHandler);
			this.dispatchEvent(event);	        
			IO.traceLog("链接成功：",this.strHost,this.iPort);
			
			var p_byteArray:ByteArrayEx;
			while(sendBuff.length>0)
			{
				p_byteArray	=	sendBuff.shift();
				send(p_byteArray);
			}
		}
		
		[Event(name = 'connectError', type = 'flash.events.Event')]
		private function onioErrorHandler(event:IOErrorEvent):void
		{
			_sprite.removeEventListener(Event.ENTER_FRAME,onCheck);
			ActSee.PostLoginStatus(22001,0,getTimer() - _time);
			//SN_PopInfo.GetInstance().ShowSimpleInfo(0, 0, "ioErrorHandler: " + String(event), false, SN_PopInfo.PopInfo_Pos_Center);
			this.dispatchEvent(event);
			IO.traceLog("ioErrorHandler: " + event);
//			Close();
//			LoginAlert.hide();
			LoginAlert.showAlert("loginFail");
			WaitingForScene.end();
			LoginUI._loginContainer.visible = true;
			
		}
		
		[Event(name = 'connectError', type = 'flash.events.Event')]
		private function onsecurityErrorHandler(event:SecurityErrorEvent):void
		{
			_sprite.removeEventListener(Event.ENTER_FRAME,onCheck);
			ActSee.PostLoginStatus(22001,0,getTimer() - _time);
			//SN_PopInfo.GetInstance().ShowSimpleInfo(0, 0, "securityErrorHandler: " + String(event), false, SN_PopInfo.PopInfo_Pos_Center);
			this.dispatchEvent(event);
			IO.traceLog("securityErrorHandler: " + event);
//			Close();
//			LoginAlert.hide();
			LoginAlert.showAlert("loginFail");
			WaitingForScene.end();
			LoginUI._loginContainer.visible = true;
		}
		
	}
}